package week07.springdsrouter;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration;
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author edward
 * @since 2021-08-07
 */
@Configuration
@EnableJdbcRepositories(basePackages = {"week07.springjdbc", "week07.springdsrouter"})
@EnableTransactionManagement
@ComponentScan(basePackages = {"week07.springjdbc", "week07.springdsrouter"})
public class DataSourceRoutingApplicationConfig extends AbstractJdbcConfiguration {

    public static final String MASTER = "master";
    public static final String SLAVES = "slaves";

    @Bean
    public DataSource getDataSourceRouter() {
        ReadWriteDataSourceRouter router = new ReadWriteDataSourceRouter();
        Map<Object, Object> dataSources = new HashMap<>();
        dataSources.put(MASTER, createMasterDataSource()); // master (单个)
        dataSources.put(SLAVES, createSlaveDataSources()); // slaves (多个)
        router.setTargetDataSources(dataSources);
        return router;
    }

    @Bean
    public NamedParameterJdbcOperations namedParameterJdbcOperations(DataSource dataSource) {
        return new NamedParameterJdbcTemplate(dataSource);
    }

    @Bean
    public TransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    JdbcTemplate getJdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    private DataSource createMasterDataSource() {
        HikariConfig config = new HikariConfig();
        config.setDriverClassName("com.mysql.cj.jdbc.Driver");
        config.setJdbcUrl("jdbc:mysql://127.0.0.1:3301/camp");
        config.setUsername("root");
        config.setPassword("");
        return new HikariDataSource(config);
    }

    private List<DataSource> createSlaveDataSources() {
        HikariConfig config = new HikariConfig();
        config.setDriverClassName("com.mysql.cj.jdbc.Driver");
        config.setJdbcUrl("jdbc:mysql://127.0.0.1:3301/camp"); // 模拟 slave
        config.setUsername("root");
        config.setPassword("");
        return Collections.singletonList(new HikariDataSource(config));
    }
}
